package com.minelx.tableui.model;

import com.minelx.table.core.Table;
import com.minelx.table.core.TableProvider;
import com.minelx.table.core.Tables;
import com.minelx.table.core.series.index.SwapIndexes;

import javax.swing.*;
import java.util.List;
import java.util.function.Function;

import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;

public class TableColumnsListModel extends AbstractListModel<String> {
	private Table table;

	private List<String> titleValues;

	private List<Long> titleIndexes;

	public TableColumnsListModel(Table table) {
		this.table = table;
		bindModel(table);
	}

	@Override
	public int getSize() {
		return titleValues.size();
	}

	@Override
	public String getElementAt(int index) {
		return titleValues.get(index);
	}

	public void innerJoin(Table joined, String on) {
		bindNew(Tables.innerJoined(table, joined, on, on));
	}

	public void remove(int selectedIndex) {
		bindModel(table.drop(singletonList(getElementAt(selectedIndex))));
		fireIntervalRemoved(this, selectedIndex, selectedIndex);
	}

	public void swap(int between, int and) {
		Long realIndexOfBetween = titleIndexes.get(between);
		Long realIndexOfAnd = titleIndexes.get(and);

		TableProvider provider = table.form().mapTitle(title -> title.mapIndexes(indexes -> new SwapIndexes(indexes, realIndexOfBetween, realIndexOfAnd)));
		bindNew(Tables.create(provider));
	}

	public void mapColumn(int columnIndex, Function<String, String> mapper) {
		long index = table.form().title().indexOf(getElementAt(columnIndex));
		Table target = Tables.create(table.form()
				.mapColumn(index, column -> column.mapSource(mapper)));
		System.out.println("target.toText() = " + target.toText());
		bindNew(target);
	}

	public void filterRows(int columnIndex, Function<String, Boolean> mapper) {
		bindNew(table.rows(table.column(getElementAt(columnIndex)).mapSource(mapper)));
	}

	public void bindNew(Table newTable) {
		bindModel(newTable);
		fireContentsChanged(this, 0, getSize());
	}

	private void bindModel(Table newTable) {
		table = newTable;
		titleValues = newTable.form().title().stream().collect(toList());
		titleIndexes = newTable.form().title().indexes().stream().boxed().collect(toList());
	}

	public Table getTable() {
		return table;
	}
}
